package com.iw.adoms.service;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.annotation.Resource;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.iw.adoms.entity.QrBatch;
import com.iw.adoms.entity.QrBoxCode;
import com.iw.adoms.entity.QrGoodsCode;
import com.iw.adoms.entity.neum.Status;
import com.iw.core.orm.hibernate.BaseDao;
import com.iw.core.orm.hibernate.BaseService;
import com.iw.core.utils.PropertiesUtil;

@Service
@Transactional
public class QrBatchService extends BaseService<QrBatch> {
	@Override
	@Resource(name = "qrBatchDao")
	public void setBaseDao(BaseDao<QrBatch> baseDao) {
		this.baseDao = baseDao;
	}

	public void create(QrBatch qrBatch) throws Exception {
		qrBatch.setStatus(Status.QR_NOT_CREATE.getValue());
		if (qrBatch.isNew()) {
			this.save(qrBatch);
		} else {
			this.update(qrBatch);
		}
		Session session = this.getBaseDao().getNewSession();
		CreateQrCode create = new CreateQrCode(qrBatch, session);
		create.start();
	}

	class CreateQrCode extends Thread {

		private QrBatch qrBatch;
		private Session session;
		// private Long boxW;
		private Long batchW;
		private Set<Long> sets = new HashSet<Long>();
		private Set<Long> boxSets = new HashSet<Long>();

		public CreateQrCode(QrBatch qrBatch, Session session) {
			this.qrBatch = qrBatch;
			this.session = session;
			this.batchW = 100000000000l + qrBatch.getId() * 1000000000l;
			// this.boxW = this.batchW + qrBatch.getBoxNum() * 100l;
			this.boxSets = rand12(qrBatch.getBoxNum());
			this.sets = rand12(qrBatch.getGoodsNum());
		}

		public void run() {
			Transaction transaction = session.beginTransaction();

			// 若有重复的数据，则先删除
			transaction.begin();
			session.createQuery("delete QrGoodsCode goods where goods.box.id in (select box.id from QrBoxCode box where box.qrBatch.id=:batchId)").setInteger("batchId", qrBatch.getId())
					.executeUpdate();
			session.createQuery("delete QrBoxCode box where box.qrBatch.id =:batchId").setInteger("batchId", qrBatch.getId()).executeUpdate();
			transaction.commit();

			// 执行数据生成
			transaction.begin();
			createBoxQrCode();

			qrBatch.setStatus(Status.QR_CREATEED.getValue());
			qrBatch.setLastUpdateTime(new Date());
			session.update(QrBatch.class.getName(), qrBatch);

			transaction.commit();
			session.close();
			this.boxSets.clear();
			sets.clear();
		}

		private void createBoxQrCode() {
			Integer boxNum = qrBatch.getBoxNum();
			Integer scale = qrBatch.getCreateScale();
			Integer batchId = qrBatch.getId();
			for (int i = 1; i <= boxNum; i++) {
				QrBoxCode box = new QrBoxCode();
				box.setQrBatch(qrBatch);
				box.setInnerNum(batchId + "-" + scale + "-" + boxNum + "-" + i);
				long liCode = this.boxSets.iterator().next();
				this.boxSets.remove(liCode);
				String wCode = String.valueOf(liCode + this.batchW);
				box.setwCode(wCode);
				box.setQrCode(PropertiesUtil.QR_PREFIX + wCode);
				// box.setPath(PropertiesUtil.QR_BOX_PATH);
				// box.setUri(PropertiesUtil.QR_BOX_URI);
				box.setGoodsNum(scale);
				box.setState(Status.WILL_IN.getValue());
				box.setInsertTime(new Date());
				session.save(QrBoxCode.class.getName(), box);
				createGoodsQrCode(box);
				if (i % 100 == 0) { // 单次批量操作的数目为100*scale
					session.flush(); // 清理缓存，执行批量插入100*scale条记录的SQL insert语句
					session.clear(); // 清空缓存中的对象
				}
			}

		}

		private void createGoodsQrCode(QrBoxCode box) {
			Integer goodsNum = box.getGoodsNum();
			Integer boxId = box.getId();
			for (int i = 1; i <= goodsNum; i++) {
				QrGoodsCode goods = new QrGoodsCode();
				goods.setBox(box);
				long lwCode = this.sets.iterator().next();
				this.sets.remove(lwCode);
				String wCode = String.valueOf(lwCode + this.batchW);
				goods.setwCode(wCode);
				goods.setQrCode(PropertiesUtil.QR_PREFIX + wCode);
				goods.setInnerNum(boxId + "-" + goodsNum + "-" + i);
				long liCode = this.sets.iterator().next();
				this.sets.remove(liCode);
				goods.setiCode(String.valueOf(liCode + this.batchW));
				goods.setState(Status.WILL_IN.getValue());
				// goods.setPath(PropertiesUtil.QR_GOODS_PATH);
				// goods.setUri(PropertiesUtil.QR_GOODS_URI);
				goods.setInsertTime(new Date());
				session.save(QrGoodsCode.class.getName(), goods);
			}
		}

		private Set<Long> rand12(Integer goodsNum) {
			Set<Long> sets = new HashSet<Long>();
			long l = 1000000000l;
			long len = goodsNum * 3L;
			if (len > l) {
				len = goodsNum * 2L;
			}
			for (long i = 0; i < len; i++) {
				double d = Math.random() * l;
				long data = Long.valueOf(Double.valueOf(d).intValue());
				while (sets.contains(data)) {
					d = Math.random() * l;
					data = Long.valueOf(Double.valueOf(d).intValue());
				}
				sets.add(data);
			}
			return sets;
		}
	}

}
